#ifndef __CODE_COMMENT_VISITOR_H_
#define __CODE_COMMENT_VISITOR_H_
#include "code_comment_info.h"

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/FileManager.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include "clang/AST/RecursiveASTVisitor.h"

#include <string>
#include <vector>
#include <map>

using namespace llvm;

class FuncCommentGenVisitor : public clang::RecursiveASTVisitor<FuncCommentGenVisitor>
{
public:
    explicit FuncCommentGenVisitor(clang::ASTContext &context, CodeCommentInfoManager& codeCommentInfoManager) 
                : mContext(context) 
                , mCodeCommentInfoManager(codeCommentInfoManager)
                , mCurrentCommentInfoPtr(nullptr)
                {}

    bool TraverseCXXMethodDecl(clang::CXXMethodDecl *D);
    bool TraverseFunctionDecl(clang::FunctionDecl *D);
    bool TraverseIfStmt(clang::IfStmt *stmt);
    bool TraverseForStmt(clang::ForStmt *stmt);
    bool TraverseWhileStmt(clang::WhileStmt *stmt);
    bool TraverseDoStmt(clang::DoStmt *stmt);
    bool TraverseSwitchStmt(clang::SwitchStmt *stmt);
    bool TraverseCaseStmt(clang::CaseStmt *stmt);
    bool TraverseDefaultStmt(clang::DefaultStmt *stmt);

    bool VisitCallExpr(const clang::CallExpr *expr);

private:
    bool getStmtStr(const clang::Stmt* stmt, std::string& stmtStr);
    bool getFile(const clang::NamedDecl *D, const clang::ASTContext &Context,
                                 std::string& fileName);
    int getLine(const clang::NamedDecl *D, const clang::ASTContext &Context);
    
    CodeCommentInfo* getCommentInfo(const clang::NamedDecl* D);
    CodeCommentInfoNode* createNewNodeWithType(const CommentType ct);
private:
    clang::ASTContext& mContext;
    CodeCommentInfoManager &mCodeCommentInfoManager;
    CodeCommentInfo*  mCurrentCommentInfoPtr;
};

#endif // __CODE_COMMENT_VISITOR_H_